/**
 * Copyright(c) 2013 Jade Techonologies Co., Ltd.
 *
 * History:
 *   14-7-29 下午2:01 Created by dwzhang
 */
package com.jade.framework.base.comm.netty;

import com.jade.framework.base.comm.*;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;

/**
 * 连接或者断开连接的处理适配器，放在第一个。
 *
 * @author dwzhang
 * @version 1.0 14-7-29 下午2:01
 */
public class ServerInboundHandler extends ChannelInboundHandlerAdapter
{
    protected Protocol protocol;
    protected NettyServer server;

    public ServerInboundHandler(NettyServer server, Protocol protocol)
    {
        this.server = server;
        this.protocol = protocol;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx)
            throws Exception
    {
        ProtocolTransport transport = server.createTransport(ctx.channel());
        ProtocolSession session = protocol.createSession(transport);
        setSession(ctx, session);
        server.addSession(session);
        ServerProtocolHandler protocolHandler = protocol.getProtocolHandler();
        if (protocolHandler != null) {
            protocolHandler.connected(session);
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx)
            throws Exception
    {
        ProtocolSession session = getSession(ctx);
        server.removeSession(session);
        ServerProtocolHandler protocolHandler = protocol.getProtocolHandler();
        if (protocolHandler != null) {
            protocolHandler.disconnected(session);
        }
    }

    @Override
     public void channelRead(ChannelHandlerContext ctx, Object msg)
             throws Exception
     {
         ProtocolSession session = getSession(ctx);
         ProtocolTransport transport = session.getTransport();
         ServerProtocolHandler protocolHandler = protocol.getProtocolHandler();
         if (msg instanceof ResponseMessage) {
             transport.onResponse((ResponseMessage)msg);
         }
         else if (msg instanceof BindMessage) {
             protocolHandler.onBind(session, msg);
         }
         else {
             protocolHandler.received(session, msg);
         }
     }

     @Override
     public void channelReadComplete(ChannelHandlerContext ctx)
             throws Exception
     {
         ctx.flush();
     }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception
    {
        ProtocolSession session = getSession(ctx);
        if (session != null) {
            ServerProtocolHandler protocolHandler = protocol.getProtocolHandler();
            if (protocolHandler != null) {
                protocolHandler.caught(session, cause);
            }
            else {
                ctx.close();
            }
        }
        else {
            protocol.getLog().warn("An unexpected error occur:", cause);
            if (ctx.channel().isActive()) {
                ctx.close();
            }
        }
    }

    private static final AttributeKey<ProtocolSession> SESSIONKEY = AttributeKey.valueOf("COMM_SESSION");

    public void setSession(ChannelHandlerContext ctx, ProtocolSession session)
    {
        Attribute<ProtocolSession> attr = ctx.attr(SESSIONKEY);
        attr.set(session);
    }

    public ProtocolSession getSession(ChannelHandlerContext ctx)
    {
        Attribute<ProtocolSession> attr = ctx.attr(SESSIONKEY);
        return attr == null ? null : attr.get();
    }

}
